home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / lib / tex / rscsencode.shar / rscsdecode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-18  |  2.2 KB  |  102 lines

  1. /*
  2.  * Stream filter to decode printable ASCII back into 8 bit bytes from
  3.  * survive most networks -- especially the RSCS community which seems
  4.  * to gobble up all sorts of the "ordinary" characters.
  5.  * Encoding is into a 64 character set "[A-Z][a-z][0-9]+-". This means
  6.  * that using 4 characters we can safely represent 3 bytes. Some overhead
  7.  * but I can take it.
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include "coder.h"
  12. char *myname;
  13.  
  14. main(argc, argv) 
  15.     char **argv;
  16. {
  17.     register int c, word, bcount;
  18.     register FILE *fin = stdin, *fout = stdout;    /* in regs for speed */
  19.     register char *map, *p;
  20.     int w;
  21.     char buf[512];
  22.     extern char *index();
  23.  
  24.     myname = argv[0];
  25.     if (argc > 2)
  26.         fprintf(stderr, "Usage: %s [file]\n", myname), exit(1);
  27.     if (argc == 2 && (fin = fopen(argv[1], "r")) == NULL) {
  28.         fprintf(stderr, "%s: ", myname);
  29.         perror(argv[1]);
  30.         exit(1);
  31.     }
  32.     /* skip to beginning of encoded data */
  33.     do {
  34.         if (fgets(buf, sizeof buf, fin) == NULL)
  35.             fatal("Missing header");
  36.         /* trim trailing blanks (sigh) */
  37.         p = index(buf, '\n');
  38.         if (p == 0)
  39.             continue;
  40.         while (*--p == ' ')
  41.             ;
  42.         p[1] = '\n';
  43.         p[2] = '\0';
  44.     } while (strcmp(buf, header) != 0);
  45.     
  46.     /* define input mapping table */
  47.     map = buf+1;
  48.     for (c = 0; c < 256; c++)
  49.         map[c] = 64;        /* illegal */
  50.     for (c = 0; c < 64; c++)
  51.         map[ENCODE(c)] = c;
  52.     map[EOF] = 65;        /* special cases */
  53.     map['/'] = 66;
  54.  
  55.     word = 0;
  56.     bcount = 4;
  57.     for (;;) {
  58.         c = map[getc(fin)];
  59.         if ((unsigned)c < 64) {
  60.             word <<= 6;
  61.             word |= c;
  62.             if (--bcount == 0) {
  63.                 putc((word >> 16) & 0xFF, fout);
  64.                 putc((word >>  8) & 0xFF, fout);
  65.                 putc((word)       & 0xFF, fout);
  66.                 word = 0;
  67.                 bcount = 4;
  68.             }
  69.             continue;
  70.         }
  71.         switch (c) {
  72.         default:
  73.             /*
  74.              * Ignore stuff not in the code set.
  75.              * I don't like this.
  76.              */
  77.             continue;
  78.         case 65:    /* EOF */
  79.             fatal("Unexpected EOF");
  80.         case 66:    /* '/' */
  81.             /* trailer follows: %d%x */
  82.             c = getc(fin) - '0';
  83.             if ((unsigned)c >= 3) /* must be 0,1,2 */
  84.                 fatal("Corrupted input (trailer)");
  85.             if (fscanf(fin, "%x", &w) != 1)
  86.                 fatal("Corrupted input (trailer)");
  87.             switch (c) {
  88.             case 2: putc((w >>  8) & 0xFF, fout);
  89.             case 1: putc((w      ) & 0xFF, fout);
  90.             }
  91.             exit(0);
  92.         }
  93.     }
  94. }
  95.  
  96. fatal(s)
  97.     char *s;
  98. {
  99.     fprintf(stderr, "%s: %s\n", myname, s);
  100.     exit(1);
  101. }
  102.